package program.Loop;

import java.util.ArrayList;

import Exceptions.ElementPlacementError;
import Exceptions.IllegalCoordinateException;
import Exceptions.PickupError;
import Exceptions.ShootException;
import Exceptions.TerminationError;
import program.Atom;
import program.SExprList;
import program.SExpression;
import program.Sequence;
import program.Command.Command;
import program.Condition.Condition;
import roborally.Robot;

/**
 * A class representing the WHILE command.
 * 
 * @author Jef Keijers/Bachelor of Science: Informatics
 * @version 1.0
 */
public class While extends Command {
	
	
	/**
	 * This constructor instanstiate a new While command with the given condition and the give command.
	 * @param 	condition
	 * @param 	body
	 */
	public While(Condition condition,Command body) {
		this.condition=condition;
		this.command1=body;
	}
	
	/**
	 * This method executes one iteration of the loop and returns the command that still has to be executed.
	 * @throws ElementPlacementError 
	 * @throws PickupError 
	 * @throws TerminationError 
	 * @throws IllegalCoordinateException 
	 * @throws ShootException  
	 */
	@Override
	public Command execute(Robot robot) throws ShootException, IllegalCoordinateException, TerminationError, PickupError, ElementPlacementError  {
		if (condition.execute(robot)) {
			ArrayList <Command> sequence=new ArrayList<Command>();
			sequence.add(command1);
			sequence.add(new While(condition,command1));
			return new Sequence(sequence).execute(robot);
		}
		return null;
	}
	
	/**
	 *	This method returns the condition.
	 */
	public Condition getCondition() {
		return condition;
	}
	
	/**
	 * Returns the SExpression representation of the WHILE loop.
	 */
	@Override
	public SExpression toSExpression() {
		SExprList sexpr = new SExprList();
		sexpr.add(new Atom("while"));
		sexpr.add(condition.toSExpression());
		sexpr.add(command1.toSExpression());
		return sexpr;
	}
	
	/**
	 * Instance variable representing the condition of the while loop.
	 */
	private Condition condition;
	/**
	 * Instance variable representing the command of the body.
	 */
	private Command command1;

}
